<?php
/*
 * ui.php created on 14 avr. 08 
 * Author: Rodrigue Le Gall
 *
 * RPortal is an open source web based Content Management System
 * Copyright (C) 2002-2008  Rodrigue Le Gall
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

class UIComponent extends Component {
	
	private static $updateEvent = array();	
	
	private $parent='';
	private $child = array();
	private $root='';
	private $template = '';
	private $render = true;
	private $update = false;
	
	public function __construct($id) {
		$this->root = $id;
		$this->setId($id);
		Component :: registerComponent($this);
		$this->init();
	}
	
	/**
	 * initialize the component : to be implemented by child class
	 */
	public function init(){
		
	}
	
	/**
	 * add a child to the component
	 */
	public function addChild(UIComponent $child){
		__trace("addChild : ".$child->getId());
		$this->child[] = $child->getId();
		$child->setParent($this);
	}
	
	/**
	 * get the childs of the component
	 * @return array components
	 */
	public function getChilds(){
		return $this->child;
	}
	
	public function setParent(UIComponent $parent){
		$this->parent=$parent->getId();
		if($this->getRoot()==$this->getId()) $this->setRoot($parent->getRoot());
	}
	/**
	 * get parent component
	 */
	 public function getParent(){
	 	return $this->search($this->parent);
	 }
	 
	 public function setRoot(UIComponent $root){
	 	$this->root=$root->getId();
	 }
	 
	 /**
	  * get the root component
	  */
	 public function getRoot(){
	 	if($this->root=='') return $this;
	 	return $this->search($this->root);
	 }
	 
	 /**
	  * delete a child
	  */
	 public function delChild($id){
	 	unset($this->child[$id]);
	 }
	 
	/**
	 * set the template path file
	 * @param string $tpl the path of the template file
	 */
	public function setTemplate($tpl){
		$this->template = realpath($tpl);
		__trace("template : ".$this->template);
	}
	
	/**
	 * define if the component has to be rendered, if not its child won't be rendered
	 * @param boolean $render true or false
	 */
	public function setRenderer($render){
		$this->render = $render;
	}
	
	/**
	 * has the component to be render
	 * @return boolean is the component rendered
	 */
	public function isRenderer(){
		return $this->render;
	}
	
	/**
	 * define that the component was updated, an event will be sent
	 */
	public function update(){
		$this->update = true;
		$this->broadcastUpdate($this->getId());
	}
	
	/**
	 * return if the component was upadted
	 * @return boolean is the component updated?
	 */
	public function isUpdated(){
		return $this->update;
	}
	
	/**
	 * render the component
	 * @return string the output
	 */
	public function render(){
		if(!$this->isRenderer()) return '';
		ob_start();
		include($this->template);
		$out = ob_get_contents();
		ob_end_clean();
		return $out;		
	}
	
	/**
	 * render all childs of the component
	 * @return string the output
	 */
	public function renderChilds(){
		$out='';
		$childs = $this->getChilds();
		foreach($childs as $key=>$child){
			$out.=$this->search($child)->render();
		}
		return $out;
	}
	
	/**
	 * render a child of the component
	 * @param string $id the id of the component
	 * @return string the output
	 */
	public function renderChild($id){
		$child = $this->search($id);
		if($child==null) return '';
		return $child->render();
	}
	
	/**
	 * register to the update event of another UIComponent
	 * @param string $cName the id of the UIComponent
	 * @param string $callback the name of the function to call
	 */
	public function register($cName,$callback){
		UIComponent :: $updateEvent[$cName][] = array($this->getId(),$callback);
		
	}

	/**
	 * broadcast a component update event
	 * this will execute the callback update of the uicomponents that listen the event
	 * @param string $event the id of the uicomponent that send the event
	 */
	public function broadcastUpdate($event){
		if(array_key_exists($event,UIComponent :: $updateEvent)){
			$broacastList = UIComponent :: $updateEvent[$event];
			for($i=0;$i<count($broacastList);$i++){
				$component = $this->search($broacastList[$i][0]);
				if($component != null){
					if($component instanceof UIComponent){
						if(!$component->isUpdated()){
							call_user_func($broacastList[$i][1],$component);
						}
					}
				}
			}
		}
	}
}